package com.laamella.syntherface.synths.alesis.micron.model;

import com.laamella.syntherface.synths.midi.MidiInterface;
import com.laamella.syntherface.synths.models.NrpnParameterModel;
import com.laamella.syntherface.synths.models.ParameterModel;
import com.laamella.syntherface.synths.models.ParameterType;

/**
 * Parameters for a single envelope.
 */
@SuppressWarnings("serial") public final class Envelope {
	public final ParameterModel attackTime;
	public final ParameterModel attackSlope;
	public final ParameterModel decayTime;
	public final ParameterModel decaySlope;
	public final ParameterModel sustainTime;
	public final ParameterModel sustainLevel;
	public final ParameterModel releaseTime;
	public final ParameterModel releaseSlope;
	public final ParameterModel velocityToEnvelope;
	public final ParameterModel resetEveryNote;
	public final ParameterModel freeRun;
	public final ParameterModel loop;
	public final ParameterModel sustainPedal;

	private final ParameterType EnvelopeTimeType = new ParameterType.IntegerRange(0, 255) {
		@Override public String format(int value) {
			if (value == maximum) {
				return "hold";
			}
			// TODO map
			return "" + value;
		}
	};

	private final ParameterType EnvelopeSlopeType = new ParameterType.List("linear, exp+, exp-");
	private final ParameterType LoopType = new ParameterType.List("off, attack/decay, entire envelope, while note held");

	public Envelope(MidiInterface midiInterface, int number) {
		int offset = (number - 1) * 13;
		String prefix = "envelope " + number + " ";
		attackTime = new NrpnParameterModel(prefix + "attack time", midiInterface, 66 + offset, EnvelopeTimeType);
		attackSlope = new NrpnParameterModel(prefix + "attack slope", midiInterface, 67 + offset, EnvelopeSlopeType);
		decayTime = new NrpnParameterModel(prefix + "decay time", midiInterface, 68 + offset, EnvelopeTimeType);
		decaySlope = new NrpnParameterModel(prefix + "decay slope", midiInterface, 69 + offset, EnvelopeSlopeType);
		sustainTime = new NrpnParameterModel(prefix + "sustain time", midiInterface, 70 + offset, EnvelopeTimeType);
		if (number == 1) {
			sustainLevel = new NrpnParameterModel(prefix + "sustain level", midiInterface, 71 + offset, ParameterType.Percentage);
		} else {
			sustainLevel = new NrpnParameterModel(prefix + "sustain level", midiInterface, 71 + offset, ParameterType.PercentageAlsoNegative);
		}
		releaseTime = new NrpnParameterModel(prefix + "release time", midiInterface, 72 + offset, EnvelopeTimeType);
		releaseSlope = new NrpnParameterModel(prefix + "release slope", midiInterface, 73 + offset, EnvelopeSlopeType);
		velocityToEnvelope = new NrpnParameterModel(prefix + "velocity to envelope", midiInterface, 74 + offset, ParameterType.Percentage);
		resetEveryNote = new NrpnParameterModel(prefix + "reset every note", midiInterface, 75 + offset, new ParameterType.Boolean(
				"reset on every note", "reset unless legato"));
		freeRun = new NrpnParameterModel(prefix + "free run", midiInterface, 76 + offset, new ParameterType.Boolean("off (do sustain)",
				"on (no sustain)"));
		loop = new NrpnParameterModel(prefix + "loop", midiInterface, 77 + offset, LoopType);
		sustainPedal = new NrpnParameterModel(prefix + "sustain pedal", midiInterface, 78 + offset, ParameterType.YesNo);
	}

}